//基类子类中都使用了动态内存
#include <iostream>
#include <cstring>
using namespace std;

class Person
{
    char *name;
public:
    //自定义构造函数
    Person(const char *n = nullptr)
    {
        if(n != nullptr)
        {
            name = new char[strlen(n)+1];
            strcpy(name,n);
        }
        else
            name = nullptr;
    }

    //实现深拷贝逻辑的拷贝构造和赋值运算
    Person(const Person &r);
    Person &operator=(const Person &r);

    //析构函数
    virtual ~Person(){delete [] name;}

    void show()
    {
        if(name!=nullptr)
            cout << "姓名:" << name;
        cout << endl;
    }
};

Person :: Person(const Person &r)
{
    if(r.name != nullptr)
    {
        name = new char[strlen(r.name)+1];
        strcpy(name,r.name);
    }
    else
        name = nullptr;
}

Person &Person :: operator=(const Person &r)
{
    delete [] name;

    if(r.name != nullptr)
    {
        name = new char[strlen(r.name)+1];
        strcpy(name,r.name);
    }
    else
        name = nullptr;

    return *this;
}

//子类
class Student : public Person
{
    char *ID;
public:
    //自定义构造函数
    Student(const char *name = nullptr,const char *id = nullptr)
        :Person(name)
    {
        if(id != nullptr)
        {
            ID = new char[strlen(id)+1];
            strcpy(ID,id);
        }
        else
            ID = nullptr;
    }

    //实现深拷贝逻辑的拷贝构造和赋值运算
    Student(const Student &r);
    Student &operator=(const Student &r);

    //析构函数
    ~Student(){delete [] ID;}

    void show()
    {
        if(ID != nullptr)
            cout << "ID:" << ID << ",";
        Person::show();
    }
};

Student :: Student(const Student &r)
   : Person(r)  //无法直接访问父类数据，此处必须显示的调用父类的拷贝构造函数，并将子类对象传入
{
    if(r.ID != nullptr)
    {
        ID= new char[strlen(r.ID)+1];
        strcpy(ID,r.ID);
    }
    else
    ID = nullptr;
}

Student &Student :: operator=(const Student &r)
{
    delete [] ID;

    Person::operator=(r);   //与上面一致，显式的调用父类的赋值操作符函数

    if(r.ID != nullptr)
    {
        ID = new char[strlen(r.ID)+1];
        strcpy(ID,r.ID);
    }
    else
    ID = nullptr;

    return *this;
}

int main(int argc, char const *argv[])
{
    Student jack("jack","100");
    jack.show();

    Student s1(jack);
    s1.show();

    Student s2;
    s2 = jack;
    s2.show();

    return 0;
}
